package com.hup.timer.presenter;

import com.hup.timer.model.TimerConfig;
import com.hup.timer.model.TimerConfig.ConfigChangedListener;
import com.hup.timer.mvp.MainMvp.MainPresenter;
import com.hup.timer.view.AppTray;
import com.hup.timer.view.TimerWindow;
import com.hup.utils.commons.hardware.ScreenUtil.ScreenChangedManager;
import com.hup.utils.commons.start.DialogHelper;
import com.hup.utils.commons.start.SimpleExitHandler;
import com.hup.utils.commons.start.SingletonAppManager;
import com.hup.utils.commons.start.SingletonAppManager.SingletonAppHandler;
import com.hup.utils.commons.start.SpringContext;
import com.hup.utils.commons.start.StartupInfo;
import com.hup.utils.commons.start.VersionConfig;
import com.hup.utils.commons.thread.TimeCatStarter;
import com.hup.utils.commons.thread.TimeCatStarter.StarterHandler;
import com.hup.utils.jna.hotkey.GlobalHotKeyListener;
import com.hup.utils.jna.hotkey.HotKey;
import lombok.Getter;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Component;

/**
 * @author hugan
 * @date 2020/1/9
 */
@Log4j2
@Component
public class MainPresenterImpl implements MainPresenter {


    private final TimeCatStarter timeCatAutoOnTop;
    private final ConfigChangedHandler configChangedHandler;
    @Getter
    private TimerConfig config;
    @Getter
    private TimerWindow timerWindow;
    private AppTray appTray;
    private SingletonAppManager singletonAppManager;

    public MainPresenterImpl() {
        config = new TimerConfig().loadFromFile();
        log.debug("config={}", config);
        log.info("version={}", SpringContext.getBean(VersionConfig.class));
        timeCatAutoOnTop = new TimeCatStarter(false);
        configChangedHandler = new ConfigChangedHandler();
        config.addConfigChangedListener(configChangedHandler);

        SpringContext.getBean(SimpleExitHandler.class).setExitAction(this::exitAction);
    }

    private void exitAction() {
        ScreenChangedManager.getInstance().removeScreenListener();
        singletonAppManager.doStop();
        appTray.doHide();
        System.exit(0);
    }

    @Override
    public void startUp() {
        singletonAppManager = SingletonAppManager.doStart(new MySingletonAppHandler());

        timerWindow = new TimerWindow();
        appTray = new AppTray(timerWindow);
        appTray.doShow();

        timerWindow.setVisible(true);
        timerWindow.doUpdateMousePenetration();
        configChangedHandler.afterConfigChanged(config);

        ScreenChangedManager.getInstance().registerScreenListener(timerWindow);
    }

    /**
     * 调用本方法与[变换可见性]的代码和逻辑比较乱,目前没有优化方案;
     *
     * 需要展示窗口的
     *      reshow:热键置顶,多实例,定时置顶
     *      托盘
     *      设置窗口[确认]
     * 要隐藏的
     *     托盘,菜单
     * 隐藏后
     *     需要禁止
     *         定时置顶,分辨率监听
     *     不需要禁止
     *         热键置顶,多实例
     * 展示时
     *     托盘,热键置顶,多实例,设置窗口[确认]
     *     如果当前不是visible,就要恢复启动
     *         定时置顶,分辨率监听
     * @param visible 即将要将窗口设置成的状态,当前状态可能不是它,也可能是
     */
    @Override
    public void beforeSwitchWindowVisible(boolean visible) {
        log.debug("visible={}", visible);
        if (visible) {
            if (!timerWindow.isVisible()) {
                //当前不是可见的,恢复服务
                configChangedHandler.handleAutoOnTop();
            }
            //else 当前是可见的,不用恢复/改变服务
        } else {
            timeCatAutoOnTop.doCancel();
        }
    }

    private class ConfigChangedHandler implements ConfigChangedListener {
        
        private HotKey hotKey = new HotKey(true, true, true, hotKey -> {
            log.info("激活置顶热键");
            beforeSwitchWindowVisible(true);
            timerWindow.reshow(false);
        });
        
        @Override
        public void afterConfigChanged(TimerConfig config) {
            handleAutoOnTop();
            handleGlobalHotKey();
        }

        private void handleAutoOnTop() {
            if (config.autoOnTop) {
                //在configChanged时,是需要restart才能改变时间间隔的
                timeCatAutoOnTop.restart("AutoOnTop-" + config.autoOnTopSpan, new StarterHandler() {
                    @Override
                    public void run(TimeCatStarter starter) {
                        log.info("已启动[自动置顶线程]");
                        starter.perSecond(config.autoOnTopSpan, () -> {
                            log.debug("AutoOnTop");
                            timerWindow.reshow(false);
                        });
                        log.info("已结束[自动置顶线程]");
                    }

                    @Override
                    public void onException(Exception e) {
                        DialogHelper.show("定时置顶错误,", e, timerWindow);
                    }
                });
            } else {
                if (timeCatAutoOnTop.isRunning()) {
                    log.info("正在取消[自动置顶线程]");
                    timeCatAutoOnTop.doCancel();
                }
            }
        }

        private void handleGlobalHotKey() {
            if (config.enableOnTopGlobalHotKey) {
                if (!GlobalHotKeyListener.contains(hotKey, true)) {
                    GlobalHotKeyListener.add(hotKey);
                }
            } else {
                GlobalHotKeyListener.removeAll();
            }
        }
    }

    private class MySingletonAppHandler implements SingletonAppHandler {
        @Override
        public int port() {
            return config.appPort;
        }

        @Override
        public String appTag() {
            return StartupInfo.getApplicationName();
        }

        @Override
        public String portSettingFileDesc() {
            return "config/TimerConfig.config的appPort";
        }

        @Override
        public void onAppReduplicateStart() {
            log.info("");
            beforeSwitchWindowVisible(true);
            timerWindow.reshow(true);
        }

    }

}
